#include <node.h>
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <sstream>

#include <node.h>
#include <v8.h>

using namespace v8;
using namespace std;

namespace nxmi {

  using v8::Local;
  using v8::Object;
  using v8::FunctionCallbackInfo;
  using v8::Isolate;
  using v8::String;
  using v8::Value;

  void Methodone(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  Local<String> retval = String::NewFromUtf8(isolate, "1adce",v8::NewStringType::kInternalized).ToLocalChecked();
  args.GetReturnValue().Set(retval);
}


void Invoke(const FunctionCallbackInfo<Value>& args){
  //printf("start call Invoke\n");
  Isolate* isolate = Isolate::GetCurrent();
  HandleScope scope(isolate);
  //v8::String::Utf8Value data(args[0]->ToString());

  v8::String::Utf8Value data(v8::Isolate::GetCurrent(), args[0]);

  std::string returnValue = std::string(*data);
  // printf("%s\n",returnValue.c_str());
  ::HINSTANCE hDLL = NULL;
  // printf("start call dll \n");

  typedef void ( __stdcall *node_invoke)(char*,char**);

  char* pBuf = new char[2048];
  memset(pBuf, 0, 2048);
  // char[] indataaaa =returnValue ;
  char* indata  = (char*) returnValue.c_str() ;

  // procedure nodeaddon_invoke(params : PChar;var result : PChar) ; stdcall ;
  // typedef char*(*pHDSerialNumRead)(string,string,string,string);
  hDLL = LoadLibrary("nxmi.dll");

  if(hDLL){
      // printf("dll Exists\n");
      node_invoke finvoke=(node_invoke)GetProcAddress(hDLL,"nodeaddon_invoke");
      if (finvoke){
          // printf("%s", indata);
          // printf("111111111111111111111111 \n");
          try{
              char* _result= (char*)malloc(2408);
              finvoke(indata,&_result);
              returnValue = _result ;
              free(_result);
          }catch(exception e){
            DWORD err = GetLastError();
            printf("%u", err);
            //printf("xxxx0");
            Local<String> retval = String::NewFromUtf8(isolate, "method invoke not Exists",v8::NewStringType::kInternalized).ToLocalChecked();
            isolate->ThrowException(Exception::TypeError(retval));
          }
      }else{
          //DWORD err = GetLastError();
          //std::string returnValue = std::string(err);
          // printf("%u", err);
          //printf("xxxx01");
          //isolate->ThrowException(Exception::TypeError(
          //                   String::NewFromUtf8(isolate, "method invoke not Exists")));
      };
  }else{
      //DWORD err = GetLastError();
      //std::string returnValue = std::string(err);
      //printf("%u", err);
      //printf("xxxx00");
      //isolate->ThrowException(Exception::TypeError(
      //          String::NewFromUtf8(isolate, "nxmi.DLL not Exists")));
  };
  FreeLibrary(hDLL) ;
  //args.GetReturnValue().Set(String::NewFromUtf8(isolate, returnValue.c_str()));

  Local<String> retval = String::NewFromUtf8(isolate, returnValue.c_str(),v8::NewStringType::kInternalized).ToLocalChecked();
  args.GetReturnValue().Set(retval);

}


void Initialize(Local<Object> exports){
    // printf("Hello node & V8 \n");
    NODE_SET_METHOD(exports, "hello", Methodone);
    NODE_SET_METHOD(exports, "invoke", Invoke);
  }


  NODE_MODULE(nxmi, Initialize)
  //NAN_MODULE_WORKER_ENABLED(nxmi,Initialize)
}